#pragma once

#include <iostream>
#include <string>
#include <unordered_map>

namespace userManager
{
    // 用户
    class user
    {
    public:
        user(const std::string &ip, const uint16_t &port) : _ip(ip), _port(port)
        {
        }
        ~user()
        {
        }

        std::string ip() const
        {
            return _ip;
        }
        uint16_t port() const
        {
            return _port;
        }
        
    private:
        std::string _ip;
        uint16_t _port;
    };

    // 在线用户
    class onlineUser
    {
    public:
        onlineUser()
        {
        }
        ~onlineUser()
        {
        }

        //
        void addUser(const std::string &ip, const uint16_t &port)
        {
            std::string id = ip + "-" + std::to_string(port);
            users.insert(std::make_pair(id, user(ip, port)));
        }
        void delUser(const std::string &ip, const uint16_t &port)
        {
            std::string id = ip + "-" + std::to_string(port);
            users.erase(id);
        }

        //
        bool isOnline(const std::string &ip, const uint16_t &port)
        {
            std::string id = ip + "-" + std::to_string(port);
            return users.count(id);
        }

        // 广播消息
        void broadcastMsg(int sockfd, const std::string& clientIP, uint16_t clientPort, const std::string &msg)
        {
            for (auto &u : users)
            {
                struct sockaddr_in client;
                bzero(&client, sizeof(client));

                client.sin_family = AF_INET;
                client.sin_port = htons(u.second.port());
                client.sin_addr.s_addr = inet_addr(u.second.ip().c_str());

                // 添加发送人相关信息
                // 下面的写法是错误的！广播转发的消息，消息前缀是消息的发送者（源），而非广播对象。
                // std::string response_msg(u.first + "# ");
                // response_msg += msg;

                // right
                std::string response_msg(clientIP + "-" + std::to_string(clientPort) + "# ");
                response_msg += msg;

                sendto(sockfd, response_msg.c_str(), response_msg.size(), 0, (struct sockaddr *)&client, sizeof(client));
            }
        }

        // 单发消息
        void singleMsg(int sockfd, const std::string& clientIP, uint16_t clientPort, std::string& msg)
        {
            struct sockaddr_in client;
            bzero(&client, sizeof(client));

            client.sin_family = AF_INET;
            client.sin_port = htons(clientPort);
            client.sin_addr.s_addr = inet_addr(clientIP.c_str());

            sendto(sockfd, msg.c_str(), msg.size(), 0, (struct sockaddr *)&client, sizeof(client));
        }

    private:
        std::unordered_map<std::string, user> users;
    };
}